From 1a5e92dd611a3b9739fa3e19c8dec1f07be9a296 Mon Sep 17 00:00:00 2001 From: Soeren Sandmann Date: Sun, 11 Jul 2004 13:26:57 +0000 Subject: [PATCH] Bug 143330, support update counter spec. Sun Jul 11 15:24:03 2004 Soeren Sandmann Bug 143330, support update counter spec. * configure.in: Add check for the Sync extension * gdk/gdkwindow.h: gdk_window_enable_synchronized_configure() and gdk_window_configure_finished() * gtk/gtkwindow.c (gtk_window_move_resize): Call gdk_window_finish_configure(). * gtk/gtkwindow.c (gtk_window_realize): Automatically enable synchronized configures. * gdk/x11/gdkwindow-x11.h (struct _GdkToplevelX11): Store current and pending counter values. * gdk/x11/gdkwindow-x11.c (gdk_window_configure_finished): New function. * gdk/x11/gdkwindow-x11.c (gdk_window_enable_synchronized_configure): New function. * gdk/x11/gdkwindow-x11.c (gdk_toplevel_x11_free_contents): Delete update counter. * gdk/x11/gdkwindow-x11.c (set_wm_protocols): Advertise _NET_WM_SYNC_REQUEST when Sync is available * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): Handle _NET_WM_SYNC_REQUEST messages * gdk/x11/gdkevents-x11.c (gdk_event_translate): Save counter value for use by gdk_window_configure_finished() when receiving ConfigureNotifies. * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add use_sync flag * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Check if the XSync extension is available * gdk/x11/gdkdisplay-x11.c: Add _NET_WM_SYNC_REQUEST and _NET_WM_SYNC_REQUEST_COUNTER to list of supported atoms. * gdk/linux-fb/gdkwindow-fb.c, gdk/win32/gdkwindow-win32.c: Add stubs for enable_synchronized_configure() and configure_finished() --- ChangeLog | 39 +++++++++++ ChangeLog.pre-2-10 | 39 +++++++++++ ChangeLog.pre-2-6 | 39 +++++++++++ ChangeLog.pre-2-8 | 39 +++++++++++ configure.in | 6 ++ gdk/gdkwindow.h | 3 + gdk/linux-fb/gdkwindow-fb.c | 10 +++ gdk/win32/gdkwindow-win32.c | 10 +++ gdk/x11/gdkdisplay-x11.c | 16 +++++ gdk/x11/gdkdisplay-x11.h | 1 + gdk/x11/gdkevents-x11.c | 46 +++++++++--- gdk/x11/gdkwindow-x11.c | 135 +++++++++++++++++++++++++++++++++--- gdk/x11/gdkwindow-x11.h | 16 ++++- gtk/gtkwindow.c | 11 ++- 14 files changed, 389 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5002b46a4e..19d419d7ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +Sun Jul 11 15:24:03 2004 Soeren Sandmann + + Bug 143330, support update counter spec. + + * configure.in: Add check for the Sync extension + + * gdk/gdkwindow.h: gdk_window_enable_synchronized_configure() and + gdk_window_configure_finished() + + * gtk/gtkwindow.c (gtk_window_move_resize): Call gdk_window_finish_configure(). + * gtk/gtkwindow.c (gtk_window_realize): Automatically enable + synchronized configures. + + * gdk/x11/gdkwindow-x11.h (struct _GdkToplevelX11): Store current + and pending counter values. + + * gdk/x11/gdkwindow-x11.c (gdk_window_configure_finished): New function. + * gdk/x11/gdkwindow-x11.c + (gdk_window_enable_synchronized_configure): New function. + * gdk/x11/gdkwindow-x11.c (gdk_toplevel_x11_free_contents): + Delete update counter. + * gdk/x11/gdkwindow-x11.c (set_wm_protocols): Advertise + _NET_WM_SYNC_REQUEST when Sync is available + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): Handle + _NET_WM_SYNC_REQUEST messages + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Save counter + value for use by gdk_window_configure_finished() when receiving + ConfigureNotifies. + + * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add use_sync flag + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Check if the XSync + extension is available + * gdk/x11/gdkdisplay-x11.c: Add _NET_WM_SYNC_REQUEST and + _NET_WM_SYNC_REQUEST_COUNTER to list of supported atoms. + + * gdk/linux-fb/gdkwindow-fb.c, gdk/win32/gdkwindow-win32.c: Add + stubs for enable_synchronized_configure() and configure_finished() + Sat Jul 10 23:35:13 2004 Matthias Clasen * gtk/gtkentry.c (paste_received): Make middle-button pasting diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 5002b46a4e..19d419d7ca 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,42 @@ +Sun Jul 11 15:24:03 2004 Soeren Sandmann + + Bug 143330, support update counter spec. + + * configure.in: Add check for the Sync extension + + * gdk/gdkwindow.h: gdk_window_enable_synchronized_configure() and + gdk_window_configure_finished() + + * gtk/gtkwindow.c (gtk_window_move_resize): Call gdk_window_finish_configure(). + * gtk/gtkwindow.c (gtk_window_realize): Automatically enable + synchronized configures. + + * gdk/x11/gdkwindow-x11.h (struct _GdkToplevelX11): Store current + and pending counter values. + + * gdk/x11/gdkwindow-x11.c (gdk_window_configure_finished): New function. + * gdk/x11/gdkwindow-x11.c + (gdk_window_enable_synchronized_configure): New function. + * gdk/x11/gdkwindow-x11.c (gdk_toplevel_x11_free_contents): + Delete update counter. + * gdk/x11/gdkwindow-x11.c (set_wm_protocols): Advertise + _NET_WM_SYNC_REQUEST when Sync is available + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): Handle + _NET_WM_SYNC_REQUEST messages + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Save counter + value for use by gdk_window_configure_finished() when receiving + ConfigureNotifies. + + * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add use_sync flag + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Check if the XSync + extension is available + * gdk/x11/gdkdisplay-x11.c: Add _NET_WM_SYNC_REQUEST and + _NET_WM_SYNC_REQUEST_COUNTER to list of supported atoms. + + * gdk/linux-fb/gdkwindow-fb.c, gdk/win32/gdkwindow-win32.c: Add + stubs for enable_synchronized_configure() and configure_finished() + Sat Jul 10 23:35:13 2004 Matthias Clasen * gtk/gtkentry.c (paste_received): Make middle-button pasting diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 5002b46a4e..19d419d7ca 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,42 @@ +Sun Jul 11 15:24:03 2004 Soeren Sandmann + + Bug 143330, support update counter spec. + + * configure.in: Add check for the Sync extension + + * gdk/gdkwindow.h: gdk_window_enable_synchronized_configure() and + gdk_window_configure_finished() + + * gtk/gtkwindow.c (gtk_window_move_resize): Call gdk_window_finish_configure(). + * gtk/gtkwindow.c (gtk_window_realize): Automatically enable + synchronized configures. + + * gdk/x11/gdkwindow-x11.h (struct _GdkToplevelX11): Store current + and pending counter values. + + * gdk/x11/gdkwindow-x11.c (gdk_window_configure_finished): New function. + * gdk/x11/gdkwindow-x11.c + (gdk_window_enable_synchronized_configure): New function. + * gdk/x11/gdkwindow-x11.c (gdk_toplevel_x11_free_contents): + Delete update counter. + * gdk/x11/gdkwindow-x11.c (set_wm_protocols): Advertise + _NET_WM_SYNC_REQUEST when Sync is available + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): Handle + _NET_WM_SYNC_REQUEST messages + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Save counter + value for use by gdk_window_configure_finished() when receiving + ConfigureNotifies. + + * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add use_sync flag + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Check if the XSync + extension is available + * gdk/x11/gdkdisplay-x11.c: Add _NET_WM_SYNC_REQUEST and + _NET_WM_SYNC_REQUEST_COUNTER to list of supported atoms. + + * gdk/linux-fb/gdkwindow-fb.c, gdk/win32/gdkwindow-win32.c: Add + stubs for enable_synchronized_configure() and configure_finished() + Sat Jul 10 23:35:13 2004 Matthias Clasen * gtk/gtkentry.c (paste_received): Make middle-button pasting diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 5002b46a4e..19d419d7ca 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,42 @@ +Sun Jul 11 15:24:03 2004 Soeren Sandmann + + Bug 143330, support update counter spec. + + * configure.in: Add check for the Sync extension + + * gdk/gdkwindow.h: gdk_window_enable_synchronized_configure() and + gdk_window_configure_finished() + + * gtk/gtkwindow.c (gtk_window_move_resize): Call gdk_window_finish_configure(). + * gtk/gtkwindow.c (gtk_window_realize): Automatically enable + synchronized configures. + + * gdk/x11/gdkwindow-x11.h (struct _GdkToplevelX11): Store current + and pending counter values. + + * gdk/x11/gdkwindow-x11.c (gdk_window_configure_finished): New function. + * gdk/x11/gdkwindow-x11.c + (gdk_window_enable_synchronized_configure): New function. + * gdk/x11/gdkwindow-x11.c (gdk_toplevel_x11_free_contents): + Delete update counter. + * gdk/x11/gdkwindow-x11.c (set_wm_protocols): Advertise + _NET_WM_SYNC_REQUEST when Sync is available + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): Handle + _NET_WM_SYNC_REQUEST messages + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Save counter + value for use by gdk_window_configure_finished() when receiving + ConfigureNotifies. + + * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add use_sync flag + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Check if the XSync + extension is available + * gdk/x11/gdkdisplay-x11.c: Add _NET_WM_SYNC_REQUEST and + _NET_WM_SYNC_REQUEST_COUNTER to list of supported atoms. + + * gdk/linux-fb/gdkwindow-fb.c, gdk/win32/gdkwindow-win32.c: Add + stubs for enable_synchronized_configure() and configure_finished() + Sat Jul 10 23:35:13 2004 Matthias Clasen * gtk/gtkentry.c (paste_received): Make middle-button pasting diff --git a/configure.in b/configure.in index 6e7d1ef561..c011f343a2 100644 --- a/configure.in +++ b/configure.in @@ -1208,6 +1208,12 @@ if test "x$gdktarget" = "xx11"; then GDK_EXTRA_LIBS="`$PKG_CONFIG --libs xcursor` $GDK_EXTRA_LIBS" fi + # X SYNC check + AC_CHECK_LIB(Xext, XSyncQueryExtension, + [GTK_ADD_LIB(x_extra_libs,Xext) + AC_DEFINE([HAVE_XSYNC], [], [Have SYNC extension])], + ,$x_libs_for_checks) + # Checks for XFixes extension have_xfixes=false diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index 83ce70391a..ce44309dc0 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -564,6 +564,9 @@ void gdk_window_get_internal_paint_info (GdkWindow *window, gint *x_offset, gint *y_offset); +void gdk_window_enable_synchronized_configure (GdkWindow *window); +void gdk_window_configure_finished (GdkWindow *window); + #ifndef GDK_MULTIHEAD_SAFE GdkPointerHooks *gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks); #endif /* GDK_MULTIHEAD_SAFE */ diff --git a/gdk/linux-fb/gdkwindow-fb.c b/gdk/linux-fb/gdkwindow-fb.c index 6f746df491..8a24025bc1 100644 --- a/gdk/linux-fb/gdkwindow-fb.c +++ b/gdk/linux-fb/gdkwindow-fb.c @@ -2359,3 +2359,13 @@ gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid) return (GdkWindow*) (anid); } + +void +gdk_window_enable_synchronized_configure (GdkWindow *window) +{ +} + +void +gdk_window_configure_finished (GdkWindow *window) +{ +} diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index cd585b1aec..87942b2915 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -3227,3 +3227,13 @@ gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid) return gdk_window_lookup (anid); } + +void +gdk_window_enable_synchronized_configure (GdkWindow *window) +{ +} + +void +gdk_window_configure_finished (GdkWindow *window); +{ +} diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index ed25df60f7..705dccacc8 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -83,6 +83,8 @@ static const char *const precache_atoms[] = { "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_FULLSCREEN", + "_NET_WM_SYNC_REQUEST", + "_NET_WM_SYNC_REQUEST_COUNTER", "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_USER_TIME", @@ -280,6 +282,20 @@ gdk_display_open (const gchar *display_name) } #endif + display_x11->use_sync = FALSE; +#ifdef HAVE_XSYNC + { + int major, minor; + int error_base, event_base; + + if (XSyncQueryExtension (display_x11->xdisplay, + &event_base, &error_base) && + XSyncInitialize (display_x11->xdisplay, + &major, &minor)) + display_x11->use_sync = TRUE; + } +#endif + _gdk_windowing_image_init (display); _gdk_events_init (display); _gdk_input_init (display); diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h index 3ce7d941aa..a523da9409 100644 --- a/gdk/x11/gdkdisplay-x11.h +++ b/gdk/x11/gdkdisplay-x11.h @@ -147,6 +147,7 @@ struct _GdkDisplayX11 guint base_dnd_atoms_precached : 1; guint xdnd_atoms_precached : 1; guint motif_atoms_precached : 1; + guint use_sync : 1; }; struct _GdkDisplayX11Class diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index b4a0ba202a..825128713b 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -46,6 +46,10 @@ #include #endif +#ifdef HAVE_XSYNC +#include +#endif + #ifdef HAVE_XFIXES #include #endif @@ -215,11 +219,10 @@ _gdk_events_init (GdkDisplay *display) display_sources = g_list_prepend (display_sources,display_source); - gdk_display_add_client_message_filter ( - display, - gdk_atom_intern ("WM_PROTOCOLS", FALSE), - gdk_wm_protocols_filter, - NULL); + gdk_display_add_client_message_filter (display, + gdk_atom_intern ("WM_PROTOCOLS", FALSE), + gdk_wm_protocols_filter, + NULL); } @@ -1723,8 +1726,16 @@ gdk_event_translate (GdkDisplay *display, !GDK_WINDOW_DESTROYED (window) && (window_private->extension_events != 0)) _gdk_input_configure_event (&xevent->xconfigure, window); + +#ifdef HAVE_XSYNC + if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value)) + { + toplevel->current_counter_value = toplevel->pending_counter_value; + XSyncIntToValue (&toplevel->pending_counter_value, 0); + } +#endif - if (!window || + if (!window || xevent->xconfigure.event != xevent->xconfigure.window || GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD || GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT) @@ -2022,8 +2033,9 @@ gdk_wm_protocols_filter (GdkXEvent *xev, XEvent *xevent = (XEvent *)xev; GdkWindow *win = event->any.window; GdkDisplay *display = GDK_WINDOW_DISPLAY (win); + Atom atom = (Atom)xevent->xclient.data.l[0]; - if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW")) + if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW")) { /* The delete window request specifies a window * to delete. We don't actually destroy the @@ -2041,7 +2053,7 @@ gdk_wm_protocols_filter (GdkXEvent *xev, return GDK_FILTER_TRANSLATE; } - else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS")) + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS")) { GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window); GdkWindowObject *private = (GdkWindowObject *)win; @@ -2056,7 +2068,7 @@ gdk_wm_protocols_filter (GdkXEvent *xev, return GDK_FILTER_REMOVE; } - else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") && + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") && !_gdk_x11_display_is_root_window (display, xevent->xclient.window)) { @@ -2070,7 +2082,21 @@ gdk_wm_protocols_filter (GdkXEvent *xev, return GDK_FILTER_REMOVE; } - + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") && + GDK_DISPLAY_X11 (display)->use_sync) + { + GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window); + if (toplevel) + { +#ifdef HAVE_XSYNC + XSyncIntsToValue (&toplevel->pending_counter_value, + xevent->xclient.data.l[2], + xevent->xclient.data.l[3]); +#endif + } + return GDK_FILTER_REMOVE; + } + return GDK_FILTER_CONTINUE; } diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index d25c0980fb..9b749909ac 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -470,13 +470,19 @@ static void set_wm_protocols (GdkWindow *window) { GdkDisplay *display = gdk_drawable_get_display (window); - Atom protocols[3]; + Atom protocols[4]; + int n = 0; - protocols[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"); - protocols[1] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"); - protocols[2] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING"); + protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"); + protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"); + protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING"); - XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, 3); +#ifdef HAVE_XSYNC + if (GDK_DISPLAY_X11 (display)->use_sync) + protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST"); +#endif + + XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n); } static const gchar * @@ -525,7 +531,8 @@ create_focus_window (Display *xdisplay, } static void -setup_toplevel_window (GdkWindow *window, GdkWindow *parent) +setup_toplevel_window (GdkWindow *window, + GdkWindow *parent) { GdkWindowObject *obj = (GdkWindowObject *)window; GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); @@ -1020,7 +1027,8 @@ gdk_window_lookup (GdkNativeWindow anid) } static void -gdk_toplevel_x11_free_contents (GdkToplevelX11 *toplevel) +gdk_toplevel_x11_free_contents (GdkDisplay *display, + GdkToplevelX11 *toplevel) { if (toplevel->icon_window) { @@ -1042,6 +1050,17 @@ gdk_toplevel_x11_free_contents (GdkToplevelX11 *toplevel) g_object_unref (toplevel->group_leader); toplevel->group_leader = NULL; } + if (toplevel->update_counter != None) + { +#ifdef HAVE_XSYNC + XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), + toplevel->update_counter); + toplevel->update_counter = None; + + XSyncIntToValue (&toplevel->current_counter_value, 0); + XSyncIntToValue (&toplevel->pending_counter_value, 0); +#endif + } } void @@ -1062,7 +1081,7 @@ _gdk_windowing_window_destroy (GdkWindow *window, toplevel = _gdk_x11_window_get_toplevel (window); if (toplevel) - gdk_toplevel_x11_free_contents (toplevel); + gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel); draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); @@ -1825,7 +1844,8 @@ gdk_window_reparent (GdkWindow *window, _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window); } - gdk_toplevel_x11_free_contents (impl->toplevel); + gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), + impl->toplevel); g_free (impl->toplevel); impl->toplevel = NULL; } @@ -5608,3 +5628,100 @@ gdk_window_begin_move_drag (GdkWindow *window, else emulate_move_drag (window, button, root_x, root_y, timestamp); } + +/** + * gdk_window_enable_synchronized_configure: + * @window: a toplevel #GdkWindow + * + * Indicates that the application will cooperate with the window + * system in synchronizing the window repaint with the window + * manager during resizing operations. After an application calls + * this function, it must call gdk_window_configure_finished() every + * time it has finished all processing associated with a set of + * Configure events. Toplevel GTK+ windows automatically use this + * protocol. + * + * On X, calling this function makes @window participate in the + * _NET_WM_SYNC_REQUEST window manager protocol. + * + * Since: 2.6 + **/ +void +gdk_window_enable_synchronized_configure (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + +#ifdef HAVE_XSYNC + if (!GDK_WINDOW_DESTROYED (window)) + { + GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + + if (toplevel && toplevel->update_counter == None && + GDK_DISPLAY_X11 (display)->use_sync) + { + Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); + XSyncValue value; + Atom atom; + + if (toplevel->update_counter != None) + return; + + XSyncIntToValue (&value, 0); + + toplevel->update_counter = XSyncCreateCounter (xdisplay, value); + + atom = gdk_x11_get_xatom_by_name_for_display (display, + "_NET_WM_SYNC_REQUEST_COUNTER"); + + XChangeProperty (xdisplay, GDK_WINDOW_XID (window), + atom, XA_CARDINAL, + 32, PropModeReplace, + (guchar *)&toplevel->update_counter, 1); + + XSyncIntToValue (&toplevel->current_counter_value, 0); + } + } +#endif /* HAVE_XSYNC */ +} + +/** + * gdk_window_configure_finished: + * @window: a toplevel #GdkWindow + * + * Signal to the window system that the application has finished + * handling Configure events it has received. Window Managers can + * use this to better synchronize the frame repaint with the + * application. GTK+ applications will automatically call this + * function when appropriate. + * + * This function can only be called if gdk_window_use_configure() + * was called previously. + * + * Since: 2.6 + **/ +void +gdk_window_configure_finished (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + +#ifdef HAVE_XSYNC + if (!GDK_WINDOW_DESTROYED (window)) + { + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); + + g_return_if_fail (toplevel->update_counter != None); + + if (toplevel && GDK_DISPLAY_X11 (display)->use_sync && + !XSyncValueIsZero (toplevel->current_counter_value)) + { + XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), + toplevel->update_counter, + toplevel->current_counter_value); + + XSyncIntToValue (&toplevel->current_counter_value, 0); + } + } +#endif +} diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index e2f160bd73..d40110f44c 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -29,6 +29,10 @@ #include +#ifdef HAVE_XSYNC +#include +#endif + G_BEGIN_DECLS typedef struct _GdkToplevelX11 GdkToplevelX11; @@ -120,13 +124,23 @@ struct _GdkToplevelX11 * that might not even be part of this app */ Window focus_window; + +#ifdef HAVE_XSYNC + XID update_counter; + XSyncValue pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */ + XSyncValue current_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received + * where we have also seen the corresponding + * ConfigureNotify + */ +#endif }; GType gdk_window_impl_x11_get_type (void); -GdkToplevelX11 *_gdk_x11_window_get_toplevel (GdkWindow *window); void gdk_x11_window_set_user_time (GdkWindow *window, guint32 timestamp); + +GdkToplevelX11 *_gdk_x11_window_get_toplevel (GdkWindow *window); void _gdk_x11_window_tmp_unset_bg (GdkWindow *window, gboolean recurse); void _gdk_x11_window_tmp_reset_bg (GdkWindow *window, diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 45d7143cba..9ffe43b7e6 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -3965,6 +3965,8 @@ gtk_window_realize (GtkWidget *widget) attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0); widget->window = gdk_window_new (parent_window, &attributes, attributes_mask); + + gdk_window_enable_synchronized_configure (widget->window); gdk_window_set_user_data (widget->window, window); @@ -4201,7 +4203,10 @@ gtk_window_configure_event (GtkWidget *widget, if (!expected_reply && (widget->allocation.width == event->width && widget->allocation.height == event->height)) - return TRUE; + { + gdk_window_configure_finished (widget->window); + return TRUE; + } /* * If we do need to resize, we do that by: @@ -5296,6 +5301,10 @@ gtk_window_move_resize (GtkWindow *window) allocation = widget->allocation; gtk_widget_size_allocate (widget, &allocation); + gdk_window_process_all_updates (); + + gdk_window_configure_finished (widget->window); + /* If the configure request changed, it means that * we either: * 1) coincidentally changed hints or widget properties -- 2.30.2